###
### Love Data - an Amiga 500 bootblock in 1024 bytes.
###   coded by Pex 'Mahoney' Tufvesson in February 2010.
###   http://mahoney.c64.org
###
###   Left mousebutton resumes normal boot procedure.
###
###   Original poetry by Joan Walsh Anglund - Buy her books, they are smart, old, pretty and awesome!
###
###   If you think this assembly code is difficult to follow, you're wrong.
###   It is, however, difficult to change, since it is self modifying, reuses registers
###   in novel ways and _will_ crash unless you know exactly what you're doing. Which I don't.
###
###   It's running ok with Amiga kernel 1.2 and 1.3, OCS, ECS or Full ECS, with or without Slowmems or Fastmems.
###   - on a Motorola ~7MHz 68000 processor as found in Amiga 500.
###
###   cross compiles under linux with GNU binutils assember for the
###   m68k-elf target.
###   Building needs Python language support on linux as well.
###
###   ToDo: If I had another 2 bytes, I'd clear screen colours at end of demo,
###         to make sure that garbage graphics wouldn't be seen.
###         But, it has more "Data" feeling with it.
###
###
### Have a noise night!
###
### / Pex 'Mahoney' Tufvesson
### http://mahoney.c64.org
### http://www.livet.se/visa
###

Bitmap = 0x70000
Bitmap2 = Bitmap + screenWidth
screenWidth = 0x50
screenHeight = 0x100  | Should be 0x032 - 0x129, but it isn't ;)

st:
DC.L  0x444F5300   |(DOS)
DC.L  0x00000000   |CHECKSUM
DC.L  0x00000370

S:
  movem.l  A0-A6/D0-D7,-(a7)
  move.w  #9,28(a1)
  clr.l  36(a1)
  jsr  -456(a6)
  lea  0xdff180,A5
  LEA  0xBFE001,A4
  OR.B  #2,(A4)
  move.l  (A6),A6
  move.l  (a6),a6
  move.l  38(a6),0x0104.w

  lea  Copper(PC),A3
  move.l  A3,0x80-0x180(A5)
  move.w  #0x8380,0x96-0x180(A5)
  move.w #0x0544,(a5)
  moveq #0,d4 |x base

  bsr.s PrintAll
Curtains:
  lsr.w #1,d7          | will make d7 #0x7fff, which is a good waiting value
waitALittle4:
  dbf d7,waitALittle4
#  btst  #6,(A4)
  bsr.s TestLButton
  beq.s ContinueBoot
  add.b #1,displayStart+1-Copper(a3)
  sub.b #1,displayStop+1-Copper(a3)
  bcc.s Curtains
  #Now, replace "flower" with optimizations:
  #dc.b 0x80+'o,'p,'t,'i,'m,'i,'z,'a,'t,'i,'o,'n,0x0d
  #0xef707469 0x6d697a61 0x74696f6e
  lea Flower-Copper(a3),a0
  move.l #0xef707469,d0
  move.l d0,(a0)+
  move.l #0x6d697a61,(a0)+
  move.l #0x74696f6e,(a0)
  move.b #0xa0,TheZero-Copper(a3)
  clr.w (a5)           | Use black as background colour
  move.w #0x94,BaseMove+2-Copper(a3)
  asl.w #1,d0          | A new colour for the chars. 0x7469 (from above) << 1 = 0x08d2, green and nice
  #move.w #0x08f8,d0
  move.w d0,Col_1+2-Copper(a3)
  move.w d0,Col_2+2-Copper(a3)
  add.w #4,LovePoi+2-Copper(a3)
  add.w #2,bold+2-Copper(a3)   |a3 points to Copper(PC)
  bsr.s PrintAll
WaitButton:
  #btst  #6,(A4)
  bsr.s TestLButton
  bne.s WaitButton

ContinueBoot:
  move.l  0x0104.w,0x80-0x180(A5)
  move.w  #0x0100,0x96-0x180(a5)
#  clr.l  (A5)   | Not enough memory to clear colours
IngenBoot:
  movem.l  (A7)+,A0-A6/D0-D7
  move.l  0x12c(a6),a0          |normal boot-continue
  move.l  0x54(a0),a0
  move.l  22(a0),a0
  moveq  #0,D0
TestLButton:
  btst  #6,(A4)
AnotherRts:
  rts

PrintAll:
  lea  Bitmap,a0
  move.l  a0,0x0108.w
PrintText:
  move.w  #(screenWidth * screenHeight / 4)-1,D7
ClrLop:
  clr.l  (A0)+
  dbf  D7,ClrLop

  lea  512(a0),A1  | A dummy area with data for the print command
  jsr  -198(A6)
  move.l  148(A6),52(A1)
  move.w  #0x8,58(A1)
  move.w  #0x4,28(A1)
  lea  128(A1),A0
  move.l  A0,4(A1)
  moveq  #1,D0
  move.w  #screenWidth * 8,D1
  jsr  -390(A6)
  move.l  0x0108.w,136(A1)
  lea S(PC),A0              |One dummy byte to write a char to, let's destroy our start byte
  moveq #0,d5 |displayStartWait
  moveq #0x79,d6 |displayStart
TextAgain:
  lea  Text(PC),A2
  moveq #0,d2 |x
  moveq #7,d3 |y
TextLoop:
  #btst  #6,(A4)
  bsr.s TestLButton
  beq.s AnotherRts
  dbf d5,noScroll
  subq #1,d6
  cmp.b #0x28,d6
  bne.s noStop
  moveq #0x29,d6
noStop:
  moveq #5,d5
  move.b d6,displayStart-Copper(a3)   |a3 points to Copper(PC)
noScroll:
  moveq  #0,D0     |A zero is needed in D0 later...
  move.b (a2)+,d1
  beq.s AnotherRts
  bpl.s noSpace
  addq #0x05,d2
  and.b #0x7f,d1
noSpace:
  cmp.b #0x0a,d1
  bne.s noNewBlock
  addq  #0x05,D3
BaseMove:
  add.b #0x29,D4 |Move base a litte for every block
  moveq #0x0d,D1
  move.w d0,bold+2-Copper(a3)   |Uses the zero in D0 above, makes the rest of the text non-bold, a3 points to Copper(PC)
noNewBlock:
  cmp.b #0x0d,d1
  bne.s noNewRow
  add.b #0x09,D3
  move.l D4,D2
  move.b (a2)+,d1
noNewRow:
  cmp.b #'L,d1
  bne.s noLove
  move.l  A2,-(A7)
LovePoi:
  lea Love(PC),a2
  move.b (a2)+,d1
  bsr.s print
  move.b (a2)+,d1
  bsr.s print
  move.b (a2)+,d1
  bsr.s print
  move.b (a2)+,d1
  move.l  (A7)+,A2
noLove:
  bsr.s print
  bra.s TextLoop    |Continue with printing text, unless lbutton pressed

print:
  move.b d1,(a0)
  #moveq  #0,D0      |D0 is already zero
  move.w  d0,36(A1)
  moveq   #1,D0          |Nof chars
bold:
  move.b  #2,56(A1)      |bold/italic/underline
  move.w  D2,36(A1)      |x-pos
  move.w  D3,38(A1)      |y-pos
  move.l  A1,-(A7)
  jsr  -60(A6)
  move.l  (A7)+,A1

  #We don't need to reset d7 to -1, since it is that already
waitALittle:
  dbf d7,waitALittle
  addq #0x08,d2     | Increment X
  rts

Text:
  dc.b 'L,0x80+'i,'s,0x80+'a,0x80+'s,'p,'e,'c,'i,'a,'l,0x80+'w,'a,'y,0x80+'o,'f,0x80+'f,'e,'e,'l,'i,'n,'g,0x0a
/*
  dc.b 'I,'t,0x80+'i,'s,0x80+'t,'h,'e,0x80+'s,'a,'f,'e,0x80+'w,'a,'y,0x80+'w,'e,0x80+'f,'e,'e,'l,0x0d
  dc.b 'w,'h,'e,'n,0x80+'w,'e,0x80+'s,'i,'t,0x80+'o,'n,0x80+'o,'u,'r,0x80+'m,'o,'t,'h,'e,'r,'','s,0x0d
  dc.b 'l,'a,'p,0x80+'w,'i,'t,'h,0x80+'h,'e,'r,0x80+'a,'r,'m,'s,0x80+'a,'r,'o,'u,'n,'d,0x80+'u,'s,0x0d
  dc.b 't,'i,'g,'h,'t,0x80+'a,'n,'d,0x80+'c,'l,'o,'s,'e,'.,0x0a
*/
  dc.b 'I,'t,0x80+'i,'s,0x80+'t,'h,'e,0x80+'g,'o,'o,'d,0x80+'w,'a,'y,0x80+'w,'e,0x80+'f,'e,'e,'l,0x0d
  dc.b 'w,'h,'e,'n,0x80+'w,'e,0x80+'t,'a,'l,'k,0x80+'t,'o,0x80+'s,'o,'m,'e,'o,'n,'e,0x0d
  dc.b 'a,'n,'d,0x80+'t,'h,'e,'y,0x80+'w,'a,'n,'t,0x80+'t,'o,0x80+'l,'i,'s,'t,'e,'n,0x0d
  dc.b 'a,'n,'d,0x80+'d,'o,'n,'','t,0x80+'t,'e,'l,'l,0x80+'u,'s,0x80+'t,'o,0x80+'g,'o,0x80+'a,'w,'a,'y,0x0d
  dc.b 'a,'n,'d,0x80+'b,'e,0x80+'q,'u,'i,'e,'t,'.,0x0a
/*
  dc.b 14,0x00,12,0x38,'I,'t,0x80+'i,'s,0x80+'t,'h,'e,0x80+'h,'a,'p,'p,'y,0x80+'w,'a,'y,0x80+'w,'e,0x0d
  dc.b 14,0x00,12,0x38,'f,'e,'e,'l,0x80+'w,'h,'e,'n,0x80+'w,'e,0x80+'s,'a,'v,'e,0x80+'a,0x0d
  dc.b 14,0x00,12,0x38,'b,'i,'r,'d,0x80+'t,'h,'a,'t,0x80+'h,'a,'s,0x80+'b,'e,'e,'n,0x80+'h,'u,'r,'t,'.,'.,'.,0x0a

  dc.b 14,0x00,12,0x38,'o,'r,0x80+'f,'e,'e,'d,0x80+'a,0x80+'l,'o,'s,'t,0x80+'c,'a,'t,'.,'.,'.,0x0a

  dc.b 14,0x00,12,0x38,'o,'r,0x80+'c,'a,'l,'m,0x80+'a,0x80+'f,'r,'i,'g,'h,'t,'e,'n,'e,'d,0x80+'c,'o,'l,'t,'.,0x0a
*/

  dc.b 'L,0x80+'i,'s,0x80+'f,'o,'u,'n,'d,0x80+'i,'n,0x80+'u,'n,'e,'x,'p,'e,'c,'t,'e,'d,0x80+'p,'l,'a,'c,'e,'s,'.,0x0d
  dc.b 'I,'t,0x80+'i,'s,0x80+'t,'h,'e,'r,'e,0x80+'i,'n,0x80+'t,'h,'e,0x80+'q,'u,'i,'e,'t,0x80+'m,'o,'m,'e,'n,'t,0x0d
  dc.b 'w,'h,'e,'n,0x80+'w,'e,0x80+'f,'i,'r,'s,'t,0x80+'d,'i,'s,'c,'o,'v,'e,'r,0x0d
  dc.b 'a,0x80+'b,'e,'a,'u,'t,'i,'f,'u,'l,0x80+'t,'h,'i,'n,'g,0x0a
/*
  dc.b 14,0x00,12,0x38,'w,'h,'e,'n,0x80+'w,'e,0x80+'w,'a,'t,'c,'h,0x80+'a,0x80+'b,'i,'r,'d,0x0d
  dc.b 14,0x00,12,0x38,'s,'o,'a,'r,0x80+'h,'i,'g,'h,0x80+'a,'g,'a,'i,'n,'s,'t,0x0d
  dc.b 14,0x00,12,0x38,'a,0x80+'p,'a,'l,'e,0x80+'b,'l,'u,'e,0x80+'s,'k,'y,'.,'.,'.,0x0a
*/
  dc.b 'w,'h,'e,'n,0x80+'w,'e,0x80+'s,'e,'e,0x80+'a,0x80+'l,'o,'v,'e,'l,'y
#Note: Flower MUST be ALIGN 2, otherwize, overwriting it with optimization will fail in the code.
Flower:
  dc.b 0x80+'f,'l,'o,'w,'e,'r,' ,' ,' ,' ,' ,' ,0x0d
#  dc.b 0x80+'o,'p,'t,'i,'m,'i,'z,'a,'t,'i,'o,'n,0x0d
  dc.b 't,'h,'a,'t,0x80+'n,'o,0x80+'o,'n,'e,0x80+'e,'l,'s,'e,0x80+'h,'a,'s,0x80+'n,'o,'t,'i,'c,'e,'d,'.,0x0a
/*
  dc.b 14,0x00,12,0x38,'w,'h,'e,'n,0x80+'w,'e,0x80+'f,'i,'n,'d,0x80+'a,0x80+'p,'l,'a,'c,'e,0x0d
  dc.b 14,0x00,12,0x38,'t,'h,'a,'t,0x80+'s,'h,'e,'l,'t,'e,'r,'s,0x80+'u,'s,0x80+'a,'n,'d,0x80+'i,'s,0x0d
  dc.b 14,0x00,12,0x38,'a,'l,'l,0x80+'o,'u,'r,0x80+'v,'e,'r,'y,0x80+'o,'w,'n,'.,0x0a
*/

  dc.b 'L,0x80+'s,'t,'a,'r,'t,'s,0x80+'i,'n,0x80+'l,'i,'t,'t,'l,'e,0x80+'w,'a,'y,'s,'.,'.,'.,0x0d
  dc.b 'I,'t,0x80+'m,'a,'y,0x80+'b,'e,'g,'i,'n,0x80+'t,'h,'e,0x80+'d,'a,'y,0x0d
  dc.b 'w,'e,0x80+'f,'i,'r,'s,'t,0x80+'s,'h,'a,'r,'e,0x80+'o,'u,'r,0x0d
  dc.b 't,'h,'o,'u,'g,'h,'t,'s,0x80+'w,'i,'t,'h,0x80+'s,'o,'m,'e,'o,'n,'e,0x80+'e,'l,'s,'e,'.,0x0a
/*
  dc.b 'o,'r,0x80+'h,'e,'l,'p,0x80+'s,'o,'m,'e,'o,'n,'e,0x80+'w,'h,'o,0x80+'n,'e,'e,'d,'s,0x80+'u,'s,'.,'.,'.,'.,0x0a

  dc.b 14,0x00,12,0x38,'O,'r,',,0x80+'s,'o,'m,'e,'t,'i,'m,'e,'s,',,0x80+'i,'t,0x80+'b,'e,'g,'i,'n,'s,0x0d
  dc.b 14,0x00,12,0x38,'b,'e,'c,'a,'u,'s,'e,',,0x80+'e,'v,'e,'n,0x80+'w,'i,'t,'h,'o,'u,'t,0x80+'w,'o,'r,'d,'s,',,0x0d
  dc.b 14,0x00,12,0x38,'w,'e,0x80+'u,'n,'d,'e,'r,'s,'t,'a,'n,'d,0x80+'h,'o,'w,0x80+'s,'o,'m,'e,'o,'n,'e,0x80+'f,'e,'e,'l,'s,'.,0x0a
*/

  dc.b 'L,0x80+'c,'o,'m,'e,'s,0x80+'q,'u,'i,'e,'t,'l,'y,0x0d
  dc.b 'b,'u,'t,0x80+'y,'o,'u,0x80+'k,'n,'o,'w,0x80+'w,'h,'e,'n,0x80+'i,'t,0x80+'i,'s,0x80+'t,'h,'e,'r,'e,',,0x0d
  dc.b 'b,'e,'c,'a,'u,'s,'e,',,0x80+'s,'u,'d,'d,'e,'n,'l,'y,'.,'.,'.,0x0d
  dc.b 'y,'o,'u,0x80+'a,'r,'e,0x80+'n,'o,'t,0x80+'a,'l,'o,'n,'e,0x80+'a,'n,'y,'m,'o,'r,'e,0x0d
  dc.b 'a,'n,'d,0x80+'t,'h,'e,'r,'e,0x80+'i,'s,0x80+'n,'o,0x80+'s,'a,'d,'n,'e,'s,'s,0x0d
  dc.b 'i,'n,'s,'i,'d,'e,0x80+'y,'o,'u,'.,0x0a

  dc.b 'L,0x80+'i,'s,0x80+'a,0x80+'h,'a,'p,'p,'y,0x80+'f,'e,'e,'l,'i,'n,'g,0x0d
  dc.b 't,'h,'a,'t,0x80+'s,'t,'a,'y,'s,0x80+'i,'n,'s,'i,'d,'e,0x80+'y,'o,'u,'r,0x80+'h,'e,'a,'r,'t,0x0d
  dc.b 'f,'o,'r,0x80+'t,'h,'e,0x80+'r,'e,'s,'t,0x80+'o,'f,0x80+'y,'o,'u,'r,0x80+'l,'i,'f,'e,'.
TheZero:
  dc.b 0x00
  dc.b 0xa0,0x80+'/,0x80+'M,'a,'h,'o,'n,'e,'y,0x80+'2,'0,'1,'0
  #dc.b 0xa0,0xa0,0x80+'/,0x80+'M,'a,'h,'o,'n,'e,'y,0x80+'F,'e,'b,0x80+'2,'0,'1,'0

  #dc.b 0x00   | This zero byte can just as well be the 0x00 found in the copper list below
ALIGN 2
Copper:
  dc.w 0x00e0,(Bitmap2/0x10000)  | BPL1PTH bitplane 1 pointers
  dc.w 0x00e2,(Bitmap2 & 0xffff) | BPL1PTL bitplane 1 pointers
Bitmap2cop:
  dc.w 0x00e4,(Bitmap /0x10000) | BPL2PTH bitplane 2 pointers
  dc.w 0x00e6,(Bitmap & 0xffff)| BPL2PTL bitplane 2 pointers
  dc.w 0x0100,0xa200            | BPLCON0 misc control bits: b15=hires, 1bit plane, color on, no interlace
  dc.w 0x0102,0x0010            | BPLCON1 scroll value PF1, PF2: playfield 2 delay=0x02
  dc.w 0x0104,0x0000            | BPLCON2 priority control: Playfield 1 har priority over pf2 and sprites
  dc.w 0x008e
displayStart:
  dc.w 0x3230            | DIWSTRT display window start (upper left vert-horiz position), y=0x44 x=0xa1
  dc.w 0x0090
displayStop:
  dc.w 0x29cf            | DIWSTOP display window stop (lower right vert-horiz position), y=0x96, x=0x08
  dc.w 0x0092,0x003c            | DDFSTRT Display bit plane data fetch start (horiz position) max_size=0x3c, 0x18 when not using sprites
  dc.w 0x0094,0x00d4            | DDFSTOP display bit plane data fetch stop (horiz position) max_size=0xd4, 0xd8
Col_1:
  dc.w 0x0182,0x0f88            | COLOR01 Color table 01
  dc.w 0x0184,0x0433            | COLOR02 Color table 02
Col_2:
  dc.w 0x0186,0x0f88            | COLOR03 Color table 03
  dc.w 0xffff,0xfffe            | Copper end
Love:
  dc.b 'L,'o,'v,'e,'D,'a,'t,'a
End:
